<?php
/**
 * @link https://www.len168.com
 * @copyright Copyright (c) 2020/9/21 len168.com
 * @author toshcn <toshcn@foxmail.com>
 */

namespace common\models;

use Yii;

/**
 * This is the model class for table "{{%menu}}".
 *
 * @property int $id
 * @property int $parent_id 父菜单id
 * @property int $sort_id 排序
 * @property int $children 下一级菜单数量
 * @property string $name 菜单名称
 * @property string $route 菜单路由名称
 * @property string $description 说明备注
 * @property string $created_at
 * @property string $updated_at
 */
class Menu extends BaseActiveRecord
{
    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return '{{%menu}}';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['created_at', 'updated_at'], 'required'],
            [['parent_id', 'sort_id', 'children'], 'integer'],
            [['parent_id', 'sort_id', 'created_at', 'updated_at'], 'safe'],
            [['name', 'route'], 'string', 'max' => 32],
            [['description'], 'string', 'max' => 128],
            [['route'], 'unique'],
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getMenuRole()
    {
        return $this->hasMany(MenuRole::class, ['menu_id' => 'id']);
    }

    /**
     * 创建菜单
     * @return bool
     */
    public function create()
    {
        $this->sort_id = (int) $this->sort_id;
        $this->created_at = $this->updated_at = date('Y-m-d H:i:s');
        $trans = Yii::$app->getDb()->beginTransaction();
        try {
            $saveParent = true;
            if ($this->parent_id) {//绑定父菜单
                $model = Menu::findOne($this->parent_id);
                $model->children = new \yii\db\Expression('`children` + 1');
                $saveParent = $model->save(false);
            }
            if ($this->save() && $saveParent) {
                $trans->commit();
                return true;
            }
        } catch (\Exception $e) {
            $this->addError('error', $e->getMessage());
            $trans->rollBack();
        }
        return false;
    }

    /**
     * 更新菜单
     * @param $parent int 原父菜单
     * @return bool
     */
    public function updateRow($parent)
    {
        $this->sort_id = (int) $this->sort_id;
        $this->updated_at = date('Y-m-d H:i:s');
        $trans = Yii::$app->getDb()->beginTransaction();
        try {
            $saveParent = $saveNewParent = true;
            if ($parent && $parent != $this->parent_id) {//解绑 减少原父菜单下级数量
                $model = Menu::findOne($parent);
                $model->children = new \yii\db\Expression('`children` - 1');
                $saveParent = $model->save(false);
            }
            if ($this->parent_id) {//绑定新父菜单
                $model = Menu::findOne($this->parent_id);
                $model->children = new \yii\db\Expression('`children` + 1');
                $saveNewParent = $model->save(false);
            }
            if ($saveParent && $saveNewParent && $this->save()) {
                $trans->commit();
                return true;
            }
        } catch (\Exception $e) {
            $this->addError('error', $e->getMessage());
            $trans->rollBack();
        }
        return false;
    }

    /**
     * @param bool $isFormat 是否整理数据
     * @return array
     */
    public static function getAllMenuData($isFormat = false)
    {
        $all = static::find()->select(['id', 'name', 'route', 'parent_id', 'children'])
            ->orderBy(['sort_id' => SORT_DESC, 'id' => SORT_ASC])
            ->asArray()
            ->all();
        if ($isFormat) {
            $all = static::formatData($all);
        }
        return $all;
    }

    /**
     * @param $data
     * @return array
     */
    public static function formatData($data)
    {
        $arr = [];
        foreach ($data as $key => $datum) {
            if ($datum['parent_id'] == 0) {
                // 一级菜单
                $temp = $datum;
                $temp['id'] = (int) $temp['id'];
                unset($data[$key]);
                if ($temp['children'] > 0) {
                    $temp['children'] = static::findChildren($temp['id'], $data);
                } else {
                    $temp['children'] = [];
                }
                $arr[] = $temp;
            }
        }
        return $arr;
    }

    public static function findChildren($parent, $data)
    {
        $arr = [];
        foreach ($data as $key => $datum) {
            if ($datum['parent_id'] == $parent) {
                // 找到子菜单
                $temp = $datum;
                $temp['id'] = (int) $temp['id'];
                unset($data[$key]);
                if ($temp['children'] > 0) {// 有下级菜单
                    $temp['children'] = static::findChildren($temp['id'], $data);
                } else {
                    $temp['children'] = [];
                }
                $arr[] = $temp;
            }
        }
        return $arr;
    }
}
